package model

import (
	"fmt"
	"github.com/nosixtools/solarlunar"
	"github.com/nosixtools/solarlunar/festival"
	"gowork/planningCalendar/pool"
	"gowork/planningCalendar/utils"
	"strconv"
	"strings"
	"sync"
	"time"
)

var newFestival = festival.NewFestival("E:/gowork/planningCalendar/model/festival.json")

type Message struct {
	Id int64 `xorm:"pk autoincr"`
	NoteId int64
	AdviserId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Note struct {
	Id int64 `xorm:"pk autoincr"`
	Type int
	Titel string
	AdviserListStr string
	ClienteListStr string
	AdviserList []*Adviser `xorm:"-"`
	ClienteList []*Client `xorm:"-"`
	ReminderDate string
	ReminderTime string
	//CompleteReminderTime time.Time `xorm:"-"`
	Repeat bool
	RepetitionMode int
	RepetitionRate int
	WeekStr string
	WeekList []string `xorm:"-"`
	EndCondition int
	Frequency int
	ReminderContent string
	IsEnd int   // 1未结束  2结束
	MessageSendTime time.Time
	CreatedAt time.Time
	UpdatedAt time.Time
}

type NoteAdviser struct {
	Id int64 `xorm:"pk autoincr"`
	NoteId int64
	AdviserId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Adviser struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type NoteClient struct {
	Id int64 `xorm:"pk autoincr"`
	NoteId int64
	ClientId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Client struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type TimePeriodReminder struct {
	TimePeriod string
	NoteList []*Note
}

func GetBetweenDates(sdate, edate string) []string {
	d := []string{}
	timeFormatTpl := "2006-01-02 15:04:05"
	if len(timeFormatTpl) != len(sdate) {
		timeFormatTpl = timeFormatTpl[0:len(sdate)]
	}
	date, err := time.Parse(timeFormatTpl, sdate)
	if err != nil {
		// 时间解析，异常
		return d
	}
	date2, err := time.Parse(timeFormatTpl, edate)
	if err != nil {
		// 时间解析，异常
		return d
	}
	if date2.Before(date) {
		// 如果结束时间小于开始时间，异常
		return d
	}
	// 输出日期格式固定
	timeFormatTpl = "2006-01-02"
	date2Str := date2.Format(timeFormatTpl)
	d = append(d, date.Format(timeFormatTpl))
	for {
		date = date.AddDate(0, 0, 1)
		dateStr := date.Format(timeFormatTpl)
		d = append(d, dateStr)
		if dateStr == date2Str {
			break
		}
	}
	return d
}

type MonthNote struct {
	Name string
	DateList []*MonthNoteDate
}

type MonthNoteDate struct {
	Name string
	LunarDate string
	HolidayVacations []string
	NoteList []*Note
}

func ZellerWeek(year, month, day int) string {

	var weekday = [7]string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}

	var y, m, c int
	if month >= 3 {
		m = month
		y = year % 100
		c = year / 100
	} else {
		m = month + 12
		y = (year - 1) % 100
		c = (year - 1) / 100
	}

	week := y + (y / 4) + (c / 4) - 2*c + ((26 * (m + 1)) / 10) + day - 1
	if week < 0 {
		week = 7 - (-week)%7
	} else {
		week = week % 7
	}
	which_week := week
	return weekday[which_week]
}

func GetMonth(m string) int{
	switch m {
	case "January":
		return 1
	case "February":
		return 2
	case "March":
		return 3
	case "April":
		return 4
	case "May":
		return 5
	case "June":
		return 6
	case "July":
		return 7
	case "August":
		return 8
	case "September":
		return 9
	case "October":
		return 10
	case "November":
		return 11
	case "December":
		return 12
	}
	return 0
}

func (note *Note)CreateNote(n *Note)(map[string]interface{}, error){

	//if n.RepetitionMode != 3 {
	//	n.MessageSendTime = n.ReminderTimeNew
	//	x.Insert(&n)
	//}
	//
	//if n.Repeat {
	//	if n.EndCondition == 1 {
	//		for i := 1; i <= 2000; i++ {
	//			if n.RepetitionMode == 1 {
	//				n.ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 0, 1)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 0, 1)
	//			} else if n.RepetitionMode == 2 {
	//				for _, d := range GetBetweenDates(time.Now().Format("2006-01-02"), time.Now().AddDate(0, 0, 2000).Format("2006-01-02")) {
	//					t, err := time.Parse("2006-01-02", d)
	//					if err != nil {
	//						return map[string]interface{}{"code": 400, "mesage": "失败"}, err
	//					}
	//					for _, w := range n.WeekList {
	//						if w == ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day()) {
	//							mst, err := time.Parse("2006-01-02 15:04:05", d+" "+n.ReminderTime)
	//							if err != nil {
	//								return map[string]interface{}{"code": 400, "mesage": "失败"}, err
	//							}
	//							n.ReminderTimeNew = mst
	//							n.MessageSendTime = mst
	//						}
	//					}
	//				}
	//			} else if n.RepetitionMode == 3 {
	//				n.ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 1, 0)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 1, 0)
	//			} else if n.RepetitionMode == 4 {
	//				n. ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 0, n.RepetitionRate)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 0, n.RepetitionRate)
	//			}
	//			x.Insert(&n)
	//
	//			for _, a := range n.AdviserList {
	//				var na = NoteAdviser{
	//					NoteId:    n.Id,
	//					AdviserId: a.Id,
	//					CreatedAt: time.Now(),
	//					UpdatedAt: time.Now(),
	//				}
	//				x.Insert(&na)
	//			}
	//
	//			for _, c := range n.ClienteList {
	//				var nc = NoteClient{
	//					NoteId:    n.Id,
	//					ClientId:  c.Id,
	//					CreatedAt: time.Now(),
	//					UpdatedAt: time.Now(),
	//				}
	//				x.Insert(&nc)
	//			}
	//		}
	//
	//	} else if n.EndCondition == 2 {
	//		for i := 1; i <= n.Frequency; i++ {
	//			if n.RepetitionMode == 1 {
	//				n. ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 0, 1)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 0, 1)
	//			} else if n.RepetitionMode == 2 {
	//				for _, d := range GetBetweenDates(time.Now().Format("2006-01-02"), time.Now().AddDate(0, 0, n.Frequency*7).Format("2006-01-02")) {
	//					t, err := time.Parse("2006-01-02", d)
	//					if err != nil {
	//						return map[string]interface{}{"code": 400, "mesage": "失败"}, err
	//					}
	//					for _, w := range n.WeekList {
	//						if w == ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day()) {
	//							mst, err := time.Parse("2006-01-02 15:04:05", d+" "+n.ReminderTime)
	//							if err != nil {
	//								return map[string]interface{}{"code": 400, "mesage": "失败"}, err
	//							}
	//							n.ReminderTimeNew = mst
	//							n.MessageSendTime = mst
	//						}
	//					}
	//				}
	//			} else if n.RepetitionMode == 3 {
	//				n. ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 1, 0)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 1, 0)
	//			} else if n.RepetitionMode == 4 {
	//				n. ReminderTimeNew = n.ReminderTimeNew.AddDate(0, 0, n.RepetitionRate)
	//				n.MessageSendTime = n.ReminderTimeNew.AddDate(0, 0, n.RepetitionRate)
	//			}
	//			x.Insert(&n)
	//
	//			for _, a := range n.AdviserList {
	//				var na = NoteAdviser{
	//					NoteId:    n.Id,
	//					AdviserId: a.Id,
	//					CreatedAt: time.Now(),
	//					UpdatedAt: time.Now(),
	//				}
	//				x.Insert(&na)
	//			}
	//
	//			for _, c := range n.ClienteList {
	//				var nc = NoteClient{
	//					NoteId:    n.Id,
	//					ClientId:  c.Id,
	//					CreatedAt: time.Now(),
	//					UpdatedAt: time.Now(),
	//				}
	//				x.Insert(&nc)
	//			}
	//		}
	//	}
	//}

	w := new(utils.Worker)

	n.Id = w.GetId()
	if n.RepetitionMode != 3 {
		loadLocation, lErr := time.LoadLocation("Asia/Shanghai")
		if lErr != nil {
			return map[string]interface{}{"code": 400, "mesage": "失败"}, lErr
		}
		messageSendTime, err := time.ParseInLocation("2006-01-02 15:04:05", n.ReminderDate+" "+n.ReminderTime, loadLocation)
		if err != nil {
			return map[string]interface{}{"code": 400, "mesage": "失败"}, err
		}
		n.MessageSendTime = messageSendTime
	}
	n.CreatedAt = time.Now()
	n.UpdatedAt = time.Now()
	x.Insert(n)

	for _, a := range strings.Split(n.AdviserListStr, ","){
		aId, err := strconv.ParseInt(a, 10, 64)
		if err != nil {
			return map[string]interface{}{"code": 400, "mesage": "失败"}, err
		}
		var na = NoteAdviser{
			Id:        w.GetId(),
			NoteId:    n.Id,
			AdviserId: aId,
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		}
		x.Insert(&na)

	}

	for _, c := range strings.Split(n.ClienteListStr, ","){
		cId, err := strconv.ParseInt(c, 10, 64)
		if err != nil {
			return map[string]interface{}{"code": 400, "mesage": "失败"}, err
		}
		var nc = NoteClient{
			Id:        w.GetId(),
			NoteId:    n.Id,
			ClientId:  cId,
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		}
		x.Insert(&nc)
	}

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (message *Message)SendMessage()(map[string]interface{}, error){

	wid := new(utils.Worker)

	var nThreeList []*Note

	now := time.Now()
	week := ZellerWeek(now.Year(), GetMonth(now.Month().String()), now.Day())

	dnow := now.Format("2006-01-02")
	rnow, _ := time.Parse("15:04:05", now.Format("15:04:05"))
	fmt.Println("rnow：", rnow)

	x.Where("is_end = ?", 1).
		And("repetition_mode = ?", 3).
		Find(&nThreeList)

	for _, nThree := range nThreeList{

		reminderTime, tErr := time.Parse("15:04:05", nThree.ReminderTime)
		if tErr != nil {
			return map[string]interface{}{"code": 400, "mesage": "失败"}, tErr
		}

		var mList []Message
		x.Where("note_id = ?", nThree.Id).And("created_at like ?", dnow+"%").Find(&mList)
		fmt.Println("mList：", mList)

		adviserList := strings.Split(nThree.AdviserListStr, ",")

		for _, w := range strings.Split(nThree.WeekStr, ","){
			if w == week {
				if reminderTime.Before(rnow) {
					if len(mList) == 0 {
						for _, a := range adviserList{
							aId, err := strconv.ParseInt(a, 10, 64)
							if err != nil {
								return map[string]interface{}{"code": 400, "mesage": "失败"}, err
							}
							var m = Message{
								Id:        wid.GetId(),
								NoteId:    nThree.Id,
								AdviserId: aId,
								CreatedAt: time.Now(),
								UpdatedAt: time.Now(),
							}
							x.Insert(&m)
						}
					}
				}
			}
		}

		if nThree.EndCondition == 2 {
			count, err := x.Where("note_id = ?", nThree.Id).Count(new(Message))
			if err != nil {
				return map[string]interface{}{"code": 400, "mesage": "失败"}, err
			}
			if count >= int64(nThree.Frequency * len(adviserList)) {
				nThree.IsEnd = 2
				x.Id(nThree.Id).Update(nThree)
			}
		}
	}

	var nList []*Note
	x.SQL("select * from note where is_end = 1 and repetition_mode in (1, 2, 4) and message_send_time <= ?", now.Format("2006-01-02 15:04:05")).Find(&nList)

	for _, n := range nList{
		adviserList := strings.Split(n.AdviserListStr, ",")
		for _, a := range adviserList{
			aId, err := strconv.ParseInt(a, 10, 64)
			if err != nil {
				return map[string]interface{}{"code": 400, "mesage": "失败"}, err
			}
			var m = Message{
				Id:        wid.GetId(),
				NoteId:    n.Id,
				AdviserId: aId,
				CreatedAt: time.Now(),
				UpdatedAt: time.Now(),
			}
			x.Insert(&m)
		}

		if n.EndCondition == 2 {
			count, err := x.Where("note_id = ?", n.Id).Count(new(Message))
			if err != nil {
				return map[string]interface{}{"code": 400, "mesage": "失败"}, err
			}
			if count >= int64(n.Frequency * len(adviserList)) {
				n.IsEnd = 2
				x.Id(n.Id).Update(n)
			}
		}

		if n.IsEnd == 1 {
			if n.RepetitionMode == 1 {
				n.MessageSendTime = n.MessageSendTime.AddDate(0, 0, 1)
			} else if n.RepetitionMode == 2 {
				n.MessageSendTime = n.MessageSendTime.AddDate(0, 1, 0)
			} else if n.RepetitionMode == 4 {
				n.MessageSendTime = n.MessageSendTime.AddDate(0, 0, n.RepetitionRate)
			}
			x.Id(n.Id).Update(n)
		}
	}

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (message *Message)SendMessageAsync()(map[string]interface{}, error){

	wid := new(utils.Worker)

	now := time.Now()
	week := ZellerWeek(now.Year(), GetMonth(now.Month().String()), now.Day())

	dnow := now.Format("2006-01-02")
	rnow, _ := time.Parse("15:04:05", now.Format("15:04:05"))
	fmt.Println("rnow：", rnow)

	p := pool.NewSimplePoll(3)
	for i := 0; i < 3; i++ {
		var finalI int = i
		p.Add(func() error{
			var nThreeList []*Note
			x.Where("is_end = ?", 1).
				And("repetition_mode = ?", 3).
				Limit(3, finalI*3).
				Find(&nThreeList)

			for _, nThree := range nThreeList{

				reminderTime, tErr := time.Parse("15:04:05", nThree.ReminderTime)
				if tErr != nil {
					return tErr
				}

				var mList []Message
				x.Where("note_id = ?", nThree.Id).And("created_at like ?", dnow+"%").Find(&mList)
				fmt.Println("mList：", mList)

				adviserList := strings.Split(nThree.AdviserListStr, ",")

				for _, w := range strings.Split(nThree.WeekStr, ","){
					if w == week {
						if reminderTime.Before(rnow) {
							if len(mList) == 0 {
								for _, a := range adviserList{
									aId, err := strconv.ParseInt(a, 10, 64)
									if err != nil {
										return err
									}
									var m = Message{
										Id:        wid.GetId(),
										NoteId:    nThree.Id,
										AdviserId: aId,
										CreatedAt: time.Now(),
										UpdatedAt: time.Now(),
									}
									x.Insert(&m)
								}
							}
						}
					}
				}

				if nThree.EndCondition == 2 {
					count, err := x.Where("note_id = ?", nThree.Id).Count(new(Message))
					if err != nil {
						return err
					}
					if count >= int64(nThree.Frequency * len(adviserList)) {
						nThree.IsEnd = 2
						x.Id(nThree.Id).Update(nThree)
					}
				}
			}

			return nil
		})
	}
	p.Run()

	pp := pool.NewSimplePoll(3)
	for i := 0; i < 3; i++ {
		var finalI int = i
		pp.Add(func() error {
			var nList []*Note
			x.SQL("select * from note where is_end = 1 and repetition_mode in (1, 2, 4) and message_send_time <= ? limit ?, ?", now.Format("2006-01-02 15:04:05"), finalI*3, 3).Find(&nList)

			for _, n := range nList{
				adviserList := strings.Split(n.AdviserListStr, ",")
				for _, a := range adviserList{
					aId, err := strconv.ParseInt(a, 10, 64)
					if err != nil {
						return err
					}
					var m = Message{
						Id:        wid.GetId(),
						NoteId:    n.Id,
						AdviserId: aId,
						CreatedAt: time.Now(),
						UpdatedAt: time.Now(),
					}
					x.Insert(&m)
				}

				if n.EndCondition == 2 {
					count, err := x.Where("note_id = ?", n.Id).Count(new(Message))
					if err != nil {
						return err
					}
					if count >= int64(n.Frequency * len(adviserList)) {
						n.IsEnd = 2
						x.Id(n.Id).Update(n)
					}
				}

				if n.IsEnd == 1 {
					if n.RepetitionMode == 1 {
						n.MessageSendTime = n.MessageSendTime.AddDate(0, 0, 1)
					} else if n.RepetitionMode == 2 {
						n.MessageSendTime = n.MessageSendTime.AddDate(0, 1, 0)
					} else if n.RepetitionMode == 4 {
						n.MessageSendTime = n.MessageSendTime.AddDate(0, 0, n.RepetitionRate)
					}
					x.Id(n.Id).Update(n)
				}
			}

			return nil
		})
	}
	pp.Run()

	return map[string]interface{}{"code":200, "message":"成功"}, nil
}

func (note *Note)QueryToDayNote(aId int64, d string) ([]*TimePeriodReminder, error){
	var tprList []*TimePeriodReminder

	var timeList []string
	for i := 0; i <= 23; i++ {
		var s string
		if i < 10{
			s = "0"+strconv.Itoa(i)+":00"
		}else {
			s = strconv.Itoa(i)+":00"
		}
		timeList = append(timeList, s)
	}

	for _, tlv := range timeList{
		var tpr = TimePeriodReminder{
			TimePeriod: tlv,
			NoteList: nil,
		}
		tprList = append(tprList, &tpr)
	}

	for _, tprv := range tprList{
		x.Join("INNER", "note_adviser", "note_adviser.note_id = note.id").
			Where("note_adviser.adviser_id = ?", aId).
			And("note.reminder_date = ?", d).
			And("note.is_end = ?", 1).
			And("note.reminder_time like ?", tprv.TimePeriod[0:3]+"%").Find(&tprv.NoteList)
	}
	return tprList, nil
}

type WeekNote struct {
	Name string
	LunarDate string
	HolidayVacations []string
	TimePeriodReminderList []*TimePeriodReminder
}

func (note *Note)QueryWeekNote(aId int64) ([]*WeekNote, error){

	//weekMap := map[string]*WeekNote{
	//	"周日":{Name:"周日"},
	//	"周一":{Name:"周一"},
	//	"周二":{Name:"周二"},
	//	"周三":{Name:"周三"},
	//	"周四":{Name:"周四"},
	//	"周五":{Name:"周五"},
	//	"周六":{Name:"周六"},
	//}

	var wnList []*WeekNote

	now := time.Now()
	offset := int(time.Monday - now.Weekday())
	if offset > 0 {
		offset = -6
	}
	var dateStrList []string

	weekStartDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
	dateStrList  = append(dateStrList, weekStartDate.Format("2006-01-02"))

	for i:=1; i<7; i++{
		dateStrList  = append(dateStrList, weekStartDate.AddDate(0,0,i).Format("2006-01-02"))

	}

	for _, dv := range dateStrList{
		t, err := time.Parse("2006-01-02", dv)
		if err != nil{
			return nil, err
		}
		getWeek := ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day())

		var wn WeekNote
		wn.Name = getWeek
		wn.LunarDate = solarlunar.SolarToChineseLuanr(dv)
		wn.HolidayVacations = newFestival.GetFestivals(dv)

		var timeList []string
		for i := 0; i <= 23; i++ {
			var s string
			if i < 10{
				s = "0"+strconv.Itoa(i)+":00"
			}else {
				s = strconv.Itoa(i)+":00"
			}
			timeList = append(timeList, s)
		}

		for _, tlv := range timeList{
			var tpr = TimePeriodReminder{
				TimePeriod: tlv,
				NoteList: nil,
			}
			wn.TimePeriodReminderList = append(wn.TimePeriodReminderList, &tpr)
		}

		for _, tprv := range wn.TimePeriodReminderList{
			x.Join("INNER", "note_adviser", "note_adviser.note_id = note.id").
				Where("note_adviser.adviser_id = ?", aId).
				And("note.reminder_date = ?",dv).
				And("note.is_end = ?", 1).
				And("note.reminder_time like ?", tprv.TimePeriod[0:3]+"%").Find(&tprv.NoteList)
		}

		//weekMap[getWeek].DateList = append(weekMap[getWeek].DateList, &wnd)

		wnList = append(wnList, &wn)
	}

	return wnList, nil
}

func (note *Note)QueryWeekNoteAsync(aId int64) ([]*WeekNote, error){

	//weekMap := map[string]*WeekNote{
	//	"周日":{Name:"周日"},
	//	"周一":{Name:"周一"},
	//	"周二":{Name:"周二"},
	//	"周三":{Name:"周三"},
	//	"周四":{Name:"周四"},
	//	"周五":{Name:"周五"},
	//	"周六":{Name:"周六"},
	//}

	var wnList []*WeekNote

	now := time.Now()
	offset := int(time.Monday - now.Weekday())
	if offset > 0 {
		offset = -6
	}
	var dateStrList []string

	weekStartDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
	dateStrList  = append(dateStrList, weekStartDate.Format("2006-01-02"))

	for i:=1; i<7; i++{
		dateStrList  = append(dateStrList, weekStartDate.AddDate(0,0,i).Format("2006-01-02"))

	}

	var wg sync.WaitGroup
	wg.Add(7)

	for i := 0; i < 7; i++ {
		actual := i
		go func() (interface{}, error){
			defer func() {
				// 捕获异常 防止waitGroup阻塞
				if err := recover(); err != nil {
					wg.Done()
				}
			}()

			dv := dateStrList[actual]
			t, err := time.Parse("2006-01-02", dv)
			if err != nil {
				return nil, err
			}
			getWeek := ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day())

			var wn WeekNote
			wn.Name = getWeek
			wn.LunarDate = solarlunar.SolarToChineseLuanr(dv)
			wn.HolidayVacations = newFestival.GetFestivals(dv)

			var timeList []string
			for i := 0; i <= 23; i++ {
				var s string
				if i < 10 {
					s = "0" + strconv.Itoa(i) + ":00"
				} else {
					s = strconv.Itoa(i) + ":00"
				}
				timeList = append(timeList, s)
			}

			for _, tlv := range timeList {
				var tpr = TimePeriodReminder{
					TimePeriod: tlv,
					NoteList:   nil,
				}
				wn.TimePeriodReminderList = append(wn.TimePeriodReminderList, &tpr)
			}

			for _, tprv := range wn.TimePeriodReminderList {
				x.Join("INNER", "note_adviser", "note_adviser.note_id = note.id").
					Where("note_adviser.adviser_id = ?", aId).
					And("note.reminder_date = ?", dv).
					And("note.is_end = ?", 1).
					And("note.reminder_time like ?", tprv.TimePeriod[0:3]+"%").Find(&tprv.NoteList)
			}

			//weekMap[getWeek].DateList = append(weekMap[getWeek].DateList, &wnd)

			wnList = append(wnList, &wn)

			wg.Done()

			return nil, nil
		}()
	}

	wg.Wait()

	return wnList, nil
}

func (note *Note)QueryMonthNote(aId int64, ym string) ([]*MonthNote, error){

	var mnList = []*MonthNote{
		{
			Name:"周日",
		},
		{
			Name:"周一",
		},
		{
			Name:"周二",
		},
		{
			Name:"周三",
		},
		{
			Name:"周四",
		},
		{
			Name:"周五",
		},
		{
			Name:"周六",
		},
	}

	now := time.Now()
	currentYear, currentMonth, _ := now.Date()
	currentLocation := now.Location()

	firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
	lastOfMonth := firstOfMonth.AddDate(0, 1, -1)

	dateList := GetBetweenDates(firstOfMonth.Format("2006-01-02"), lastOfMonth.Format("2006-01-02"))
	for _, dv := range dateList{
		t, err := time.Parse("2006-01-02", dv)
		if err != nil{
			return nil, err
		}
		getWeek := ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day())

		var mnd MonthNoteDate
		mnd.Name = dv
		mnd.LunarDate = solarlunar.SolarToChineseLuanr(dv)
		mnd.HolidayVacations = newFestival.GetFestivals(dv)

		x.Join("INNER", "note_adviser", "note_adviser.note_id = note.id").
			Where("note_adviser.adviser_id = ?", aId).
			And("note.reminder_date = ?", dv).
			And("note.is_end = ?", 1).
			Find(&mnd.NoteList)

		switch getWeek {
		case "周日":
			mnList[0].DateList = append(mnList[0].DateList, &mnd)
		case "周一":
			mnList[1].DateList = append(mnList[1].DateList, &mnd)
		case "周二":
			mnList[2].DateList = append(mnList[2].DateList, &mnd)
		case "周三":
			mnList[3].DateList = append(mnList[3].DateList, &mnd)
		case "周四":
			mnList[4].DateList = append(mnList[4].DateList, &mnd)
		case "周五":
			mnList[5].DateList = append(mnList[5].DateList, &mnd)
		case "周六":
			mnList[6].DateList = append(mnList[6].DateList, &mnd)
		}
	}

	return mnList, nil
}

func (note *Note)QueryMonthNoteAsync(aId int64, ym string) ([]*MonthNote, error){

	var mnList = []*MonthNote{
		{
			Name:"周日",
		},
		{
			Name:"周一",
		},
		{
			Name:"周二",
		},
		{
			Name:"周三",
		},
		{
			Name:"周四",
		},
		{
			Name:"周五",
		},
		{
			Name:"周六",
		},
	}

	now := time.Now()
	currentYear, currentMonth, _ := now.Date()
	currentLocation := now.Location()

	firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
	lastOfMonth := firstOfMonth.AddDate(0, 1, -1)

	dateList := GetBetweenDates(firstOfMonth.Format("2006-01-02"), lastOfMonth.Format("2006-01-02"))

	var wg sync.WaitGroup
	wg.Add(10)

	for i := 0; i < 10; i++ {
		actual := i
		go func() (interface{}, error){
			defer func() {
				// 捕获异常 防止waitGroup阻塞
				if err := recover(); err != nil {
					wg.Done()
				}
			}()

			for _, dv := range dateList[actual*3:(actual+1)*3] {
				t, err := time.Parse("2006-01-02", dv)
				if err != nil {
					return nil, err
				}
				getWeek := ZellerWeek(t.Year(), GetMonth(t.Month().String()), t.Day())

				var mnd MonthNoteDate
				mnd.Name = dv
				mnd.LunarDate = solarlunar.SolarToChineseLuanr(dv)
				mnd.HolidayVacations = newFestival.GetFestivals(dv)

				x.Join("INNER", "note_adviser", "note_adviser.note_id = note.id").
					Where("note_adviser.adviser_id = ?", aId).
					And("note.reminder_date = ?", dv).
					And("note.is_end = ?", 1).
					Find(&mnd.NoteList)

				switch getWeek {
				case "周日":
					mnList[0].DateList = append(mnList[0].DateList, &mnd)
				case "周一":
					mnList[1].DateList = append(mnList[1].DateList, &mnd)
				case "周二":
					mnList[2].DateList = append(mnList[2].DateList, &mnd)
				case "周三":
					mnList[3].DateList = append(mnList[3].DateList, &mnd)
				case "周四":
					mnList[4].DateList = append(mnList[4].DateList, &mnd)
				case "周五":
					mnList[5].DateList = append(mnList[5].DateList, &mnd)
				case "周六":
					mnList[6].DateList = append(mnList[6].DateList, &mnd)
				}
			}

			wg.Done()

			return nil, nil
		}()
	}

	wg.Wait()

	return mnList, nil
}